package com.yanlight.app.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.yanlight.app.dal.dao.AdCountDAO;
import com.yanlight.app.dal.dao.AwardRecordDAO;
import com.yanlight.app.dal.entity.AdCount;
import com.yanlight.app.dal.entity.AwardItem;
import com.yanlight.app.dal.entity.AwardRecord;
import com.yanlight.app.request.AliTransferRequest;
import com.yanlight.app.response.WxCouponResponse;
import com.yanlight.app.response.WxRedPacketResponse;
import com.yanlight.app.response.WxTransfersResponse;
import com.yanlight.app.service.AdCountService;
import com.yanlight.exception.ErrorType;
import com.yanlight.support.AppConstants;
import com.yanlight.support.alipay.AlipayConstants;
import com.yanlight.support.alipay.request.AlipayNotifyPayRequest;
import com.yanlight.support.http.Response;
import com.yanlight.support.wx.request.WxPayNotifyRequest;
import com.yanlight.type.PayType;
import com.yanlight.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class AdCountServiceImpl implements AdCountService {

    @Autowired
    AdCountDAO adCountDao;

    @Autowired
    AwardRecordDAO awardRecordDAO;

    @Override
    public Response clickCount(AdCount adCount) {
        adCount.setClickTime(DateTimeUtil.getNowTime());

        Response response;
        Integer count = adCountDao.countItemByDay(adCount.getType(), adCount.getAuthId(), adCount.getCompanyId(), adCount.getCodeValue());
        //今天红包数量已经完成，再点击不会再有红包
        if (count > AppConstants.getRedPacketLimit()) {
            response = ResponseUtil.fail(ErrorType.RED_PACKET_LIMIT);
        } else {
            response = ResponseUtil.success();
        }
        adCountDao.save(adCount);
        return response;
    }

    /**
     * @param type      2 微信  1 支付宝
     * @param authId
     * @param companyId
     * @param codeValue
     * @return
     */
    @Override
    public Response verifyAward(Integer type, String authId, Long companyId, String codeValue) {

        Integer count = adCountDao.countItemByDay(type, authId, companyId, codeValue);
        if (count > AppConstants.getRedPacketLimit()) {
            return ResponseUtil.fail(ErrorType.RED_PACKET_LIMIT);
        }

        AdCount adCount = adCountDao.queryByAuthId(type, authId, companyId, codeValue);

        if (adCount == null) {
            return ResponseUtil.fail(ErrorType.RED_PACKET_TASK);
        }

        if (adCount.isUsed()) {
            return ResponseUtil.fail(ErrorType.RED_PACKET_TASK);
        }

        adCountDao.updateUsedStatus(adCount.getId(), true);

        //支付宝
        if (type == 1) {

        }
        //微信
        else if (type == 2) {
            WxCouponResponse wxCouponResponse = WxCouponUtil.grantCoupon(authId);
        }
        //调用发送满减红包接口
        return ResponseUtil.success();
    }

    @Override
    public boolean isShowRedPacket(Integer type, String authId, Long companyId, String codeValue) {
        Integer count = adCountDao.countItemByDay(type, authId, companyId, codeValue);
        if (count > AppConstants.getRedPacketLimit()) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Integer todayAwardTimes(String authId) {
        //今日已抽奖次数
        Integer used = adCountDao.todayAwardTimes(authId, true);

        if (used >= AppConstants.getRedPacketLimit()) {
            return 0;
        }

        Integer unused = adCountDao.todayAwardTimes(authId, false);

        int enable = AppConstants.getRedPacketLimit() - used;

        if (unused >= enable) {
            return enable;
        } else {
            return unused;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer getResult(String authId, Integer type) {
        //更新抽奖次数
        AdCount adCount = adCountDao.selectNewestOne(authId);
        if (adCount == null) {
            return -1;
        }
        //计算中奖概率
        int index = DrawLotteryUtil.drawAwardItem();
        AwardItem awardItem = DrawLotteryUtil.getAwardItem(index);

        //支付宝
        if (type.equals(PayType.ALIPAY.getType())) {
            if (awardItem.getType() == 1 || awardItem.getType() == 2) {
                Integer amount = (int) (awardItem.getAmount() * 100);
                adCountDao.updateUsedStatus(adCount.getId(), true);
                AlipayFundTransUniTransferResponse response = aliTransfer(authId, awardItem.getAmount());
                if (response != null && response.isSuccess()) {
                    LogUtil.showLog("转账结果", response);
                    String orderId = response.getOrderId();
                    String outBizNo = response.getOutBizNo();
                    saveAwardRecord(authId, adCount.getId(), amount, type, 1, outBizNo, orderId);
                } else {
                    return DrawLotteryUtil.getNoPrizeIndex();
                }
            }
        }
        //微信
        else if (type.equals(PayType.WXPAY.getType())) {
            Integer amount = (int) (awardItem.getAmount() * 100);
            adCountDao.updateUsedStatus(adCount.getId(), true);
            //现金转账
            if (awardItem.getType() == 1) {
                WxTransfersResponse transfers = WxHttpClientUtil.transfers(authId, amount);
                if (transfers.isSuccess()) {
                    saveAwardRecord(authId, adCount.getId(), amount, type, 1, transfers.getPayment_no(), transfers.getPayment_no());
                } else {
                    return DrawLotteryUtil.getNoPrizeIndex();
                }
            }
            //现金红包
            else if (awardItem.getType() == 2) {
                //单位转换为分

                WxRedPacketResponse redPacketResponse = WxHttpClientUtil.sendRedPacket(authId, amount);
                if (redPacketResponse.isSuccess()) {
                    saveAwardRecord(authId, adCount.getId(), amount, type, 2, redPacketResponse.getMch_billno(), redPacketResponse.getSend_listid());
                    adCountDao.updateUsedStatus(adCount.getId(), true);
                } else {
                    return DrawLotteryUtil.getNoPrizeIndex();
                }
            }
        }

        return index;
    }

    @Override
    public void firstPayIncrease(String packets, Long companyId, Integer payType) {

        if (PayType.ALIPAY.getType().equals(payType)) {
            AlipayNotifyPayRequest notifyRequest = new AlipayNotifyPayRequest(packets);
            String authAppId = notifyRequest.getBuyerId();
            savePayCount(companyId, authAppId, PayType.ALIPAY.getType());
        } else if (PayType.WXPAY.getType().equals(payType)) {
            WxPayNotifyRequest notifyRequest = new WxPayNotifyRequest(packets);
            String authId = notifyRequest.getOpenId();
            savePayCount(companyId, authId, PayType.WXPAY.getType());
        }
    }

    private void savePayCount(Long companyId, String authId, Integer type) {
        //查询当前用户是否因为支付获得过抽奖机会
        Integer count = adCountDao.selectPayCountToday(authId);
        if (count == null || count == 0) {
            AdCount adCount = new AdCount();
            adCount.setCompanyId(companyId);
            adCount.setAuthId(authId);
            adCount.setType(type);
            adCount.setClickTime(DateTimeUtil.getNowTime());
            adCount.setPay(true);
            adCountDao.save(adCount);
        }
    }

    private AlipayFundTransUniTransferResponse aliTransfer(String authId, double amount) {
        AlipayFundTransUniTransferResponse response = null;
        try {
            AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();

            CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
            certAlipayRequest.setServerUrl(AlipayConstants.gateway);
            certAlipayRequest.setAppId(AlipayConstants.mchAppId);

            certAlipayRequest.setPrivateKey(AlipayConstants.mchPrivateKey);
            certAlipayRequest.setCharset("utf-8");
            certAlipayRequest.setFormat("JSON");
            certAlipayRequest.setSignType("RSA2");

            certAlipayRequest.setCertPath(AlipayConstants.mchCertPath);
            certAlipayRequest.setAlipayPublicCertPath(AlipayConstants.mchPublicCertPath);
            certAlipayRequest.setRootCertPath(AlipayConstants.mchRootCertPath);

            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

            String nowTimeNoChar = DateTimeUtil.getNowTimeNoChar();
            String orderNumber = AlipayConstants.appId + nowTimeNoChar + RandomStringUtil.randomNumeric(4);

            AliTransferRequest requestEntity = new AliTransferRequest();
            requestEntity.setOut_biz_no(orderNumber);
            requestEntity.setRemark("转盘抽奖");
            requestEntity.setOrder_title("转盘抽奖");
            requestEntity.setTrans_amount(amount);

            AliTransferRequest.PayeeInfo payeeInfo = new AliTransferRequest.PayeeInfo(authId);
            requestEntity.setPayee_info(payeeInfo);

            request.setBizContent(JSONObject.toJSONString(requestEntity));
            response = alipayClient.certificateExecute(request);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.showLog("支付宝转账", e.getMessage());
        }
        return response;
    }

    private void saveAwardRecord(String authId, Long adCountId, Integer amount, Integer payType, Integer sendType, String busiNo, String platformNo) {
        AwardRecord awardRecord = new AwardRecord();
        awardRecord.setAdCountId(adCountId);
        awardRecord.setAmount(amount);
        awardRecord.setAuthId(authId);
        awardRecord.setPayType(payType);
        awardRecord.setSendType(sendType);
        awardRecord.setSendTime(DateTimeUtil.getNowTime());
        awardRecord.setBusiOrderNo(busiNo);
        awardRecord.setPlatformNo(platformNo);
        awardRecord.setStatus(true);

        awardRecordDAO.save(awardRecord);
    }

}
